# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
# 1. 获取用户数据/提交信息/提交代码
import subprocess
import sys
from datetime import datetime
from pyecharts import options as opts
from pyecharts.charts import Bar, Pie, Tab

import pandas as pd


def get_info(git_path):
    out = subprocess.check_output(['git', 'log', '--format=----\n%H,%aN,%ct,%P,%s', '--numstat'], cwd=git_path)
    out_string = out.decode(encoding="utf8").strip()
    commits = out_string.split("----\n")
    # print("commits:", commits)
    lines = []
    infos = []
    for i in commits[1:]:
        i_split = i.strip().split("\n")
        # print("data:", data)
        info = dict(zip(["hash", "name", "time", "parent", "commit"], i_split[0].split(",")))
        time_local = datetime.fromtimestamp(int(info["time"]))
        info["time"] = time_local
        infos.append(info)
        for dline in i_split[2:]:
            # print("dline:", dline)
            line = dict(zip(["add", "minus", "filename"], dline.split("\t")))
            line.update({"hash": info["hash"]})
            lines.append(line)
            # print("line:", line)
    fileLines = pd.DataFrame(lines)
    fileLines["add"] = fileLines["add"].replace("-", "0").astype("float")
    fileLines["minus"] = fileLines["minus"].replace("-", "0").astype("float")
    commits = pd.DataFrame(infos)
    return fileLines, commits


def sats_commit_num(comm):
    commits = comm.copy()
    commits["day"] = commits["time"].apply(lambda x: x.strftime("%Y-%m-%d"))
    out = commits.groupby(["name", "day"])["hash"].count()
    out = out.reset_index()
    out = out.pivot(index="name", columns="day", values="hash").fillna(0)
    colums = out.columns.to_list()
    start_range = 1 - 20 / len(colums)
    c = (Bar().
        add_xaxis(colums).
        set_global_opts(
        title_opts=opts.TitleOpts(title="提交次数"),
        datazoom_opts=opts.DataZoomOpts(
            range_start=start_range * 100,
            range_end=100,

        ))
    )
    for i, v in out.iterrows():
        c.add_yaxis(i, list(v), stack="stack1")
    c.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    return c


def stats_autor_contribute(comm, d):
    commits = comm.copy()
    data = d.copy()
    commits["day"] = commits["time"].apply(lambda x: x.strftime("%Y-%m-%d"))
    with_go = data["filename"].apply(lambda x: x.endswith('.go'))
    out = data[with_go].groupby("hash")
    out = out[["add", "minus"]].sum()
    out["all"] = out["add"] - out["minus"]
    out = commits.set_index("hash").join(out, how="outer")
    out = out.groupby("name")["all"].sum()
    c = (
        Pie()
            .add("", [[i, j] for i, j in out.items()])
            .set_global_opts(title_opts=opts.TitleOpts(title="代码贡献"))
            .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))

    )
    return c


file_list = []


def end_with(filename):
    if len(file_list) == 0:
        return True
    for f in file_list:
        if filename.endswith(f):
            return True
    return False


def stats_autor_lines(comm, d):
    commits = comm.copy()
    data = d.copy()
    commits["day"] = commits["time"].apply(lambda x: x.strftime("%Y-%m-%d"))
    with_go = data["filename"].apply(end_with)
    out = data[with_go].groupby("hash")
    out = out[["add", "minus"]].sum()
    out["all"] = out["add"] - out["minus"]
    # print("out", out)
    out = commits.set_index("hash").join(out, how="outer")
    # print(out)
    out = out.groupby(["name", "day"])["all"].sum()
    out = out.reset_index()
    out = out.pivot(index="name", columns="day", values="all").fillna(0)
    colums = out.columns.to_list()
    start_range = 1 - 20 / len(colums)
    c = (Bar().
        add_xaxis(colums).
        set_global_opts(
        title_opts=opts.TitleOpts(title="代码行数"),
        datazoom_opts=opts.DataZoomOpts(
            range_start=start_range * 100,
            range_end=100,

        ))
    )
    for i, v in out.iterrows():
        c.add_yaxis(i, list(v), stack="stack1")
    c.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    return c


if __name__ == '__main__':
    if len(sys.argv) > 1:
        path = sys.argv[1]
    else:
        path = "./"
    data, commits = get_info(path)
    p1 = sats_commit_num(commits)
    p2 = stats_autor_contribute(commits, data)
    p3 = stats_autor_lines(commits, data)
    tab = Tab()
    tab.add(p1, "提交次数")
    tab.add(p3, "代码行数")
    tab.add(p2, "代码贡献")
    tab.render("git-status.html")
